package com.hsd.znsh.utils;


import com.hsd.znsh.enums.ResultEnum;
import com.hsd.znsh.exception.ZnshException;
import com.hsd.znsh.hql.*;
import jdk.nashorn.internal.ir.annotations.Ignore;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.util.StringUtils;

import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

public class HqlUtil {

    private static String getClassName(Object object){
        Class objectClass=object.getClass();
        Annotation annotation=objectClass.getAnnotation(ClassName.class);
        if(annotation!=null){
            ClassName className=(ClassName)annotation;
            return  className.value().getSimpleName();
        }else{
            return object.getClass().getSimpleName();
        }
    }

    private static String[] getOrProperties(Object object){
        Class objectClass=object.getClass();
        Annotation annotation=objectClass.getAnnotation(Or.class);
        if(annotation!=null){
            Or or=(Or)annotation;
            return  or.properties();
        }else{
            return new String[0];
        }
    }

    private static String getSingleAnnotation(Field field,String propertyName,Object srcValue){
        String where="";
        boolean likeFlag=true;
        Ignore ignore=field.getAnnotation(Ignore.class);
        if(ignore!=null){
            return where;
        }

        Equal equal=field.getAnnotation(Equal.class);
        String columnName=propertyName;
        if(equal!=null){
            if(!equal.column().equals("")) columnName=equal.column();
            where+=" and "+columnName+" = :"+propertyName;
            likeFlag=false;
        }

        NotEqual notEqual=field.getAnnotation(NotEqual.class);
        if(notEqual!=null){
            if(!notEqual.column().equals("")) columnName=notEqual.column();
            where+=" and "+columnName+" != :"+propertyName;
            likeFlag=false;
        }

        Great great=field.getAnnotation(Great.class);
        if(great!=null){
            if(!great.column().equals("")) columnName=great.column();
            where+=" and "+columnName+" > :"+propertyName;
            likeFlag=false;
        }

        Less less=field.getAnnotation(Less.class);
        if(less!=null){
            if(!less.column().equals("")) columnName=less.column();
            where+=" and "+columnName+" < :"+propertyName;
            likeFlag=false;
        }

        In in=field.getAnnotation(In.class);
        if(in!=null){
            if(!in.column().equals("")) columnName=in.column();
            where+=" and "+columnName+" in(:"+propertyName+")";
            likeFlag=false;
        }

        NotIn notIn=field.getAnnotation(NotIn.class);
        if(notIn!=null){
            if(!notIn.column().equals("")) columnName=notIn.column();
            where+=" and "+columnName+" not in(:"+propertyName+")";
            likeFlag=false;
        }

        Null null1=field.getAnnotation(Null.class);
        if(null1!=null){
            where+=" and "+columnName+" is null";
        }

        NotNull notNull=field.getAnnotation(NotNull.class);
        if(notNull!=null){
            where+=" and "+columnName+" is not null";
        }

        Like like=field.getAnnotation(Like.class);
        if(like!=null){
            if(!like.column().equals("")) columnName=like.column();
            where+=" and "+columnName+" like '%"+srcValue+"%'";
            likeFlag=false;
        }
        if(likeFlag) where+=" and "+propertyName+" like '%"+srcValue+"%'";
        return where;
    }

    private static String getMoreAnnotation(Field field,String columnName,String propertyName,Object srcValue){
        String where=" ( 0=1 ";

        Equal equal=field.getAnnotation(Equal.class);
        if(equal!=null){
            where+=" or "+columnName+" = :"+propertyName;
        }

        NotEqual notEqual=field.getAnnotation(NotEqual.class);
        if(notEqual!=null){
            where+=" or "+columnName+" != :"+propertyName;
        }

        Great great=field.getAnnotation(Great.class);
        if(great!=null){
            where+=" or "+columnName+" > :"+propertyName;
        }

        Less less=field.getAnnotation(Less.class);
        if(less!=null){
            where+=" or "+columnName+" < :"+propertyName;
        }

        In in=field.getAnnotation(In.class);
        if(in!=null){
            where+=" or "+columnName+" in(:"+propertyName+")";
        }

        NotIn notIn=field.getAnnotation(NotIn.class);
        if(notIn!=null){
            where+=" or "+columnName+" not in(:"+propertyName+")";
        }

        Null null1=field.getAnnotation(Null.class);
        if(null1!=null){
            where+=" or "+columnName+" is null";
        }

        NotNull notNull=field.getAnnotation(NotNull.class);
        if(notNull!=null){
            where+=" or "+columnName+" is not null";
        }

        Like like=field.getAnnotation(Like.class);
        if(like!=null){
            where+=" or "+columnName+" like '%"+srcValue+"%'";
        }
        where+=" )";
        return where;
    }

    private static String getWhereHql (Object object){
        try{
            String where="";
            Class objectClass=object.getClass();
            final BeanWrapper src = new BeanWrapperImpl(object);

            PropertyDescriptor[] pds = src.getPropertyDescriptors();
            for(PropertyDescriptor pd : pds) {
                Object srcValue = src.getPropertyValue(pd.getName());
                if (srcValue == null||pd.getName().equals("class")) continue;
                if(srcValue instanceof String){
                    if(StringUtils.isEmpty(srcValue)) continue;
                }
                Field field=objectClass.getDeclaredField(pd.getName());
                String columnName=pd.getName();
                Or or=field.getAnnotation(Or.class);
                if(or!=null){
                    if(!or.column().equals("")) columnName=or.column();
                    where+=" and "+getMoreAnnotation(field,columnName,pd.getName(),srcValue);
                }else{
                    where+=getSingleAnnotation(field,pd.getName(),srcValue);
                }
            }
            return where;
        }catch (Exception e){
            e.printStackTrace();
            throw new ZnshException(ResultEnum.SERVER_ERROR);
        }
    }

    public static String getQueryHql(Object object) {
        String hql="from "+getClassName(object)+" where 1=1 ";
        hql+=getWhereHql(object);
        return hql;
    }

    public static String getCountHql(Object object) {
        String hql="select count(*) from "+getClassName(object)+" where 1=1 ";
        hql+=getWhereHql(object);
        return hql;
    }

}
